Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit e266279538bf47b33cde5881e75a6e95d8b39041


Parents : 272f060
Author : Ivan <ivan@quad4.io>
Signature : Signature validation error
Date : 2026-04-13T23:34:08-05:00

feat(build): add script to unify non-binary files between arm64 and x64 cx_Freeze outputs for SHA check compliance

Changes

2 files changed, 56 insertions(+), 0 deletions(-)


Diff

diff --git a/scripts/build-macos-universal.sh b/scripts/build-macos-universal.sh
index 8bb2eac0..da4f9d4d 100644
--- a/scripts/build-macos-universal.sh
+++ b/scripts/build-macos-universal.sh
@@ -22,4 +22,13 @@ if [[ -n "${PYTHON_CMD_X64:-}" ]]; then
else
cross-env ARCH=x64 pnpm run build-backend
fi
+
+# @electron/universal v2.x checks SHA equality for every non-Mach-O file
+# and throws if any differ (no x64ArchFiles escape for PLAIN files).
+# cx_Freeze's library.zip contains only architecture-independent Python
+# bytecode; the per-arch native extensions (.dylib/.so) live outside the
+# zip. The two zips differ solely in .pyc header timestamps and zip
+# metadata, so copying one over the other is safe and makes the merge pass.
+bash scripts/unify-backend-plain-files.sh
+
exec pnpm exec electron-builder --mac --universal --publish=never

diff --git a/scripts/unify-backend-plain-files.sh b/scripts/unify-backend-plain-files.sh
new file mode 100755
index 00000000..2d6b7885
--- /dev/null
+++ b/scripts/unify-backend-plain-files.sh
@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+# Ensure non-binary files in the two per-arch cx_Freeze outputs are
+# byte-identical so @electron/universal's SHA check passes.
+#
+# Python bytecode (.pyc inside library.zip) is architecture-independent;
+# only timestamps and zip metadata differ between the arm64 and x64
+# builds. Native extensions (.dylib/.so) are Mach-O binaries and
+# handled separately by lipo, so they are excluded here.
+set -euo pipefail
+
+ROOT="$(cd "$(dirname "$0")/.." && pwd)"
+
+ARM64_DIR="$ROOT/build/exe/darwin-arm64"
+X64_DIR="$ROOT/build/exe/darwin-x64"
+
+if [[ ! -d "$ARM64_DIR" || ! -d "$X64_DIR" ]]; then
+ echo "unify-backend-plain-files: one or both backend dirs missing, skipping"
+ exit 0
+fi
+
+unified=0
+
+while IFS= read -r -d '' rel; do
+ arm64_file="$ARM64_DIR/$rel"
+ x64_file="$X64_DIR/$rel"
+
+ [[ -f "$x64_file" ]] || continue
+
+ if cmp -s "$arm64_file" "$x64_file"; then
+ continue
+ fi
+
+ filetype=$(file --brief --no-pad "$arm64_file" 2>/dev/null || true)
+ if [[ "$filetype" == Mach-O* ]]; then
+ continue
+ fi
+
+ cp "$arm64_file" "$x64_file"
+ echo " unified: $rel"
+ unified=$((unified + 1))
+done < <(cd "$ARM64_DIR" && find . -type f -print0 | sed -z 's|^\./||')
+
+if [[ $unified -gt 0 ]]; then
+ echo "unify-backend-plain-files: copied $unified file(s) from arm64 → x64"
+else
+ echo "unify-backend-plain-files: all non-binary files already identical"
+fi


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────